﻿using ExcelUnity.Core;
using ExcelUnity.Importer.Attributes;
using ExcelUnity.Importer.Importers;
using System;
using System.Reflection;
using System.Text.RegularExpressions;

namespace ExcelUnity.Importer.Wrappers
{
    /// <summary>
    /// Excel的列与用户对象属性的关系
    /// </summary>
    public class ColumnProperty
    {
        public ColumnProperty(PropertyInfo property, ColumnIndexAttribute attr)
        {
            MatchColumnName = property.Name;
            PropertyInfo = property;
            MatchColumnIndex = attr.Index;
            ColumnMatchType = ColumnMatchType.ColumnIndex;
            SetValidateData(property);
        }

        public ColumnProperty(PropertyInfo property, ColumnNameAttribute attr)
        {
            MatchColumnName = attr.Name;
            PropertyInfo = property;
            ColumnMatchType = ColumnMatchType.ColumnName;
            SetValidateData(property);
        }

        /// <summary>
        /// 用户对象与表格索引的匹配下标
        /// </summary>
        public int? MatchColumnIndex { get; set; }

        /// <summary>
        /// 用户对象与表格列名的匹配名称
        /// </summary>
        public string? MatchColumnName { get; set; }

        /// <summary>
        ///  用户对象与表格列的匹配方式
        /// </summary>
        public ColumnMatchType ColumnMatchType { get; set; }

        /// <summary>
        /// 对应的用户对象属性
        /// </summary>
        public PropertyInfo PropertyInfo { get; set; }

        /// <summary>
        /// 是否需要正则验证
        /// </summary>
        public bool HasRegex { get; set; }

        /// <summary>
        /// 正则匹配表达式
        /// </summary>
        public string? RegexPattern { get; set; }

        /// <summary>
        /// 正则选项
        /// </summary>
        public RegexOptions RegexOptions { get; set; }

        /// <summary>
        /// 正则匹配失败错误提示
        /// </summary>
        public string RegexErrorMessage { get; set; } = "数据不符合规则";

        /// <summary>
        /// 是否是必须的（不可为空）
        /// </summary>
        public bool IsRequired { get; set; }

        /// <summary>
        /// 是否参与唯一验证
        /// </summary>
        public bool IsUnique { get; set; }

        /// <summary>
        /// 数据为空时的提示
        /// </summary>
        public string EmptyErrorMessage { get; set; } = "数据不可为空";

        /// <summary>
        /// 属性赋值
        /// </summary>
        /// <param name="value"></param>
        /// <param name="targetData"></param>
        /// <param name="errorHandler"></param>
        public void FillDataPropertyValue(string value, object targetData, Action<string, string> errorHandler)
        {
            if (!ValidatePropertyValueFormat(value, (propertyName, errorMessage) => errorHandler(propertyName, errorMessage)))
                return;

            if (value.IsNotNullOrWhiteSpace())
            {
                //可为空的Nullable泛型获取目标类型
                var targetType = PropertyInfo.IsNullable() ? PropertyInfo.PropertyType.GetGenericArguments()[0]
                                                           : PropertyInfo.PropertyType;
                try
                {
                    PropertyInfo.SetValue(targetData, CommonHelper.ConvertValueType(value, targetType));
                }
                catch (Exception ex)
                {
                    errorHandler(PropertyInfo.Name, $"数据转换异常:{ex.Message}.");
                }
            }
        }

        /// <summary>
        /// 校验属性值规范
        /// </summary>
        /// <param name="value"></param>
        /// <param name="errorHandler"></param>
        /// <returns></returns>
        private bool ValidatePropertyValueFormat(string value, Action<string, string> errorHandler)
        {
            if (value.IsNullOrWhiteSpace() && IsRequired)
            {
                errorHandler(PropertyInfo.Name, EmptyErrorMessage);
                return false;
            }

            if (HasRegex && !Regex.IsMatch(value, RegexPattern, RegexOptions))
            {
                errorHandler(PropertyInfo.Name, RegexErrorMessage);
                return false;
            }

            return true;
        }

        private void SetValidateData(PropertyInfo property)
        {
            if (property.GetCustomAttribute(typeof(ColumnRegexAttribute)) is ColumnRegexAttribute attr2)
            {
                HasRegex = attr2.Pattern != null;
                RegexPattern = attr2.Pattern;
                RegexErrorMessage = attr2.ErrorMessage;
                RegexOptions = attr2.RegexOptions;
            }

            if (property.GetCustomAttribute(typeof(ColumnRequiredAttribute)) is ColumnRequiredAttribute attr3)
            {
                IsRequired = true;
                EmptyErrorMessage = attr3.EmptyErrorMessage;
            }

            if (property.GetCustomAttribute(typeof(ColumnUniqueAttribute)) is ColumnUniqueAttribute)
                IsUnique = true;

            if (!property.IsNullable() && property.PropertyType != typeof(string))
                IsRequired = true;
        }
    }
}
